﻿#pragma warning(disable: 4996)
#pragma warning(disable: 6031)

/*
二分法求函数根的原理为：如果连续函数f(x)在区间[a,b]的两个端点取值异号，即f(a)f(b)<0，则它在这个区间内至少存在1个根r，即f(r)=0。

二分法的步骤为：

检查区间长度，如果小于给定阈值，则停止，输出区间中点(a+b)/2；否则
如果f(a)f(b)<0，则计算中点的值f((a+b)/2)；
如果f((a+b)/2)正好为0，则(a+b)/2就是要求的根；否则
如果f((a+b)/2)与f(a)同号，则说明根在区间[(a+b)/2,b]，令a=(a+b)/2，重复循环；
如果f((a+b)/2)与f(b)同号，则说明根在区间[a,(a+b)/2]，令b=(a+b)/2，重复循环。
本题目要求编写程序，计算给定3阶多项式f(x)=a​3​​ x​3​​ +a​2​​ x​2​​ +a​1​​ x+a​0​​ 在给定区间[a,b]内的根。

输入格式：
输入在第1行中顺序给出多项式的4个系数a​3​​ 、a​2​​ 、a​1​​ 、a​0​​ ，在第2行中顺序给出区间端点a和b。题目保证多项式在给定区间内存在唯一单根。

输出格式：
在一行中输出该多项式在该区间内的根，精确到小数点后2位。

输入样例：
3 -1 -3 1
-0.5 0.5
输出样例：
0.33
*/

#include <stdio.h>
typedef float Real;
#define EPS 0.000001

static inline sgn(Real a)
{
	if (a > EPS)
		return 1;
	else if (a < -EPS)
		return -1;
	return 0;
}

struct Polynomial {
	Real a[100];
	int n;
};

Real f(struct Polynomial* p, Real x)
{
	Real ret = p->a[p->n];
	for (int i = p->n - 1; i >= 0; --i) {
		ret = ret * x + p->a[i];
	}
	return ret;
}

Real polynomial_binary_root(struct Polynomial* p, Real a, Real b)
{
	Real ret = a;
	Real ya = f(p, a);
	int sa = sgn(ya);
	Real yb = f(p, b);
	Real yc = 0;
	if (yb == 0)
		return b;
	while (ya * yb < 0)
	{
		ret = (a + b)/2;
		yc = f(p, ret);
		int sc = sgn(yc);
		if (sc == 0)
			break;
		if (sc == sa)
			a = ret;
		else
			b = ret;
	}
	return ret;
}

void polynomial_read(struct Polynomial* p)
{
	p->n = 3;
	for (int i = p->n; i >= 0; --i)
		scanf("%f", &p->a[i]);
}

void solve() {
	struct Polynomial p;
	Real a, b, root = 0;
	polynomial_read(&p);
	scanf("%f %f", &a, &b);
	root = polynomial_binary_root(&p, a, b);
	printf("%.2f\n", root);
}

int main()
{
	freopen("D:/Develop/GitRepos/MOOC/浙江大学/数据结构/201906/DataStructure/M2019秋C入门和进阶练习集/7-29.txt", "r", stdin);
	solve();
	return 0;
}